import 'package:flutter/foundation.dart';
import 'package:get/get.dart';
import 'package:ichinesereader/models/book/BookItem.dart';
import 'package:ichinesereader/utils/play_button_notifier.dart';
import 'package:ichinesereader/utils/progress_notifier.dart';
import 'package:ichinesereader/utils/repeat_button_notifier.dart';
import 'package:just_audio/just_audio.dart';

//import '../models/book/RecordLocation.dart';
//import 'package:ichinesereader/service/book.dart';
/////// https://suragch.medium.com/managing-playlists-in-flutter-with-just-audio-c4b8f2af12eb

class AudioBooksController extends GetxController {
  final currentBookTitleNotifier = ValueNotifier<String>('');
  final playlistNotifier = ValueNotifier<List<String>>([]);
  final progressNotifier = ProgressNotifier();
  final repeatButtonNotifier = RepeatButtonNotifier();
  final isFirstSongNotifier = ValueNotifier<bool>(true);
  final playButtonNotifier = PlayButtonNotifier();
  final isLastSongNotifier = ValueNotifier<bool>(true);
  final isShuffleModeEnabledNotifier = ValueNotifier<bool>(false);
  //BookServiceProvider _bookServiceProvider = new BookServiceProvider();

  late AudioPlayer _audioPlayer;
  late ConcatenatingAudioSource _playlist;
  List<BookItem> books = [];
  @override
  void onInit() async {
    _audioPlayer = AudioPlayer();
    //  _setInitialPlaylist();
    _listenForChangesInPlayerState();
    _listenForChangesInPlayerPosition();
    _listenForChangesInBufferedPosition();
    _listenForChangesInTotalDuration();
    _listenForChangesInSequenceState();
    super.onInit();
  }

  // @override
  // dispose() {
  //  // super.dispose();
  // }
  void setCurrentBookTitleNotifier(String title) {
    currentBookTitleNotifier.value = title;
  }

  void setPlaylist(List<BookItem> abooks) async {
    if (abooks.length > 0) {
      this.books = abooks;
      List<AudioSource> audioBooks = [];
      abooks.forEach((book) {
        audioBooks.add(AudioSource.uri(Uri.parse(book.audio.toString()),
            tag: book.bookTitle));
      });
      _playlist = ConcatenatingAudioSource(children: audioBooks);
      await _audioPlayer.setAudioSource(_playlist);
    }
  }

  void _listenForChangesInPlayerState() {
    _audioPlayer.playerStateStream.listen((playerState) {
      final isPlaying = playerState.playing;
      final processingState = playerState.processingState;
      if (processingState == ProcessingState.loading ||
          processingState == ProcessingState.buffering) {
        playButtonNotifier.value = ButtonState.loading;
      } else if (!isPlaying) {
        playButtonNotifier.value = ButtonState.paused;
      } else if (processingState != ProcessingState.completed) {
        playButtonNotifier.value = ButtonState.playing;
      } else {
        _audioPlayer.seek(Duration.zero);
        _audioPlayer.pause();
      }
    });
  }

  void _listenForChangesInPlayerPosition() {
    _audioPlayer.positionStream.listen((position) {
      final oldState = progressNotifier.value;
      progressNotifier.value = ProgressBarState(
        current: position,
        buffered: oldState.buffered,
        total: oldState.total,
      );
    });
  }

  void _listenForChangesInBufferedPosition() {
    _audioPlayer.bufferedPositionStream.listen((bufferedPosition) {
      final oldState = progressNotifier.value;
      progressNotifier.value = ProgressBarState(
        current: oldState.current,
        buffered: bufferedPosition,
        total: oldState.total,
      );
    });
  }

  void _listenForChangesInTotalDuration() {
    _audioPlayer.durationStream.listen((totalDuration) {
      final oldState = progressNotifier.value;
      progressNotifier.value = ProgressBarState(
        current: oldState.current,
        buffered: oldState.buffered,
        total: totalDuration ?? Duration.zero,
      );
    });
  }

  void _listenForChangesInSequenceState() {
    _audioPlayer.sequenceStateStream.listen((sequenceState) {
      if (sequenceState == null) return;

      // update current book title
      final currentItem = sequenceState.currentSource;
      final title = currentItem?.tag as String?;
      currentBookTitleNotifier.value = title ?? '';

      // update playlist
      final playlist = sequenceState.effectiveSequence;
      final titles = playlist.map((item) => item.tag as String).toList();
      playlistNotifier.value = titles;

      // update shuffle mode
      isShuffleModeEnabledNotifier.value = sequenceState.shuffleModeEnabled;

      // update previous and next buttons
      if (playlist.isEmpty || currentItem == null) {
        isFirstSongNotifier.value = true;
        isLastSongNotifier.value = true;
      } else {
        isFirstSongNotifier.value = playlist.first == currentItem;
        isLastSongNotifier.value = playlist.last == currentItem;
      }
    });
  }

  void play() async {
    _audioPlayer.play();
  }

  void stop() async {
    _audioPlayer.stop();
  }

  void pause() {
    _audioPlayer.pause();
  }

  void seek(Duration position) {
    _audioPlayer.seek(position);
  }

  void onRepeatButtonPressed() {
    repeatButtonNotifier.nextState();
    switch (repeatButtonNotifier.value) {
      case RepeatState.off:
        _audioPlayer.setLoopMode(LoopMode.off);
        break;
      case RepeatState.repeatSong:
        _audioPlayer.setLoopMode(LoopMode.one);
        break;
      case RepeatState.repeatPlaylist:
        _audioPlayer.setLoopMode(LoopMode.all);
    }
  }

  void onPreviousSongButtonPressed() {
    _audioPlayer.seekToPrevious();
  }

  void onNextSongButtonPressed() {
    _audioPlayer.seekToNext();
  }

  void onShuffleButtonPressed() async {
    final enable = !_audioPlayer.shuffleModeEnabled;
    if (enable) {
      await _audioPlayer.shuffle();
    }
    await _audioPlayer.setShuffleModeEnabled(enable);
  }

  void addAudioBook() {}

  void removeAudioBook() {}

  void setRecordlist(String url) async {
    List<AudioSource> audioBooks = [];
    audioBooks
        .add(AudioSource.uri(Uri.parse(url.toString()), tag: 'recording'));
    _playlist = ConcatenatingAudioSource(children: audioBooks);
    await _audioPlayer.setAudioSource(_playlist);
  }

  void setRecord(String url) async {
    //Log.debug('url----from  audio mangeer----5---$url');
    try {
      await _audioPlayer.setAudioSource(
          AudioSource.uri(Uri.parse(url.toString())),
          preload: true);
    } catch (error) {
      print('open audio file: $error');
      await _audioPlayer.setAudioSource(
          AudioSource.uri(Uri.parse(url.toString())),
          preload: false);
    }
  }

  void setRecordPreload(String url) async {
    //Log.debug('url----from  audio mangeer----5---$url');
    await _audioPlayer
        .setAudioSource(AudioSource.uri(Uri.parse(url.toString())));
  }
}
